package com.unitd.modules.configcenter.util;

import com.alibaba.fastjson.JSON;
import com.unitd.modules.configcenter.entity.AppConfigs;
import com.unitd.frame.comm.utils.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;

import java.io.StringReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/** * @desc 解析配置中心的属性配置(文件)信息的工具类
 * @filename ConfigParseUtils.java
 * @copyright www.unitd.com
 * @author Hudan
 * @version 1.0
 * @date 2018/1/27
 */
public class ConfigParseUtils {

	/**
	 * @desc 将属性配置信息对象解析成key-value对象并存入map对象
	 * @param config 属性配置信息对象
	 * @return Map
	 */
	public static Map<String, Object> parseConfigToKVMap(AppConfigs config) {
		Map<String, Object> result = new HashMap<>(1);
		parseConfigToKVMap(result, config);
		return result;
	}

	/**
	 * @desc 将属性配置信息对象解析成key-value对象并存入map对象
	 * @param result 存储解析后的key-value值
	 * @param config 属性配置信息对象
	 */
	@SuppressWarnings("unchecked")
	public static void parseConfigToKVMap(Map<String, Object> result, AppConfigs config) {
		if (config.getType() == 1) {
			if (config.getName().toLowerCase().endsWith(".xml")) {
				parseDataFromXML(result, config.getContents());
			} else {
				parseFromProps(result, config.getContents());
			}
		} else if (config.getType() == 2) {
			result.put(config.getName(), config.getContents());
		} else if (config.getType() == 3) {
			Map<String, Object> configs = JSON.parseObject(config.getContents(), Map.class);
			result.putAll(configs);
		}

		//替换引用
		String value;
		for (String key : result.keySet()) {
			value = StringUtils.trimToEmpty(result.get(key).toString());
			if (value.contains("${")) {
				setReplaceHolderRefValue(result, key, value);
			}
		}
	}

	/**
	 * @desc 设置某些替换值
	 * @param result 解析后的key-value值
	 * @param key 默认的key
	 * @param value 需要进行替换的值
	 */
	public static void setReplaceHolderRefValue(Map<String, Object> result, String key, String value) {

		String[] segments = value.split("\\$\\{");
		String seg;

		StringBuilder finalValue = new StringBuilder();
		for (int i = 0; i < segments.length; i++) {
			seg = StringUtils.trimToNull(segments[i]);
			if (StringUtils.isBlank(seg)) continue;

			if (seg.contains("}")) {
				String refKey = seg.substring(0, seg.indexOf("}")).trim();
				//其他非${}的占位符如：{{host}}
				String withBraceString = null;
				if (seg.contains("{")) {
					withBraceString = seg.substring(seg.indexOf("}") + 1);
				}

				//如果包含默认值，如：${host:127.0.0.1}
				String orginKey = refKey;
				if (refKey.contains(":")) {
					refKey = refKey.split(":")[0];
				}

				String refValue = result.containsKey(refKey) ? result.get(refKey).toString() : "${" + orginKey + "}";
				finalValue.append(refValue);

				if (withBraceString != null) {
					finalValue.append(withBraceString);
				} else {
					String[] segments2 = seg.split("\\}");
					if (segments2.length == 2) {
						finalValue.append(segments2[1]);
					}
				}
			} else {
				finalValue.append(seg);
			}
		}

		result.put(key, finalValue.toString());
	}

	/**
	 * @desc 将字符串中的属性配置信息对象解析成key-value对象并存入map对象
	 * @param result 存储解析后的key-value值
	 * @param content 属性配置信息字符串
	 */
	public static void parseFromProps(Map<String, Object> result, String content) {
		String[] lines = content.split("\n");
		for (String line : lines) {
			if (StringUtils.isBlank(line) || line.startsWith("#") || line.indexOf("=") < 0) continue;
			//考虑 value包含=的情况
			String key = line.substring(0, line.indexOf("=")).trim();
			String value = line.substring(line.indexOf("=") + 1).trim();
			if (StringUtils.isNotBlank(value)) {
				result.put(key, value);
			}
		}
	}

	/**
	 * @desc 将xml串中的属性配置信息对象解析成key-value对象并存入map对象
	 * @param result 存储解析后的key-value值
	 * @param xmlContents 属性配置信息的xml串
	 */
	private static void parseDataFromXML(Map<String, Object> result, String xmlContents) {
		Document doc;
		try {
			//doc = DocumentHelper.parseText(xmlContents);
			SAXReader reader = new SAXReader();
			//忽略dtd验证
			reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
			InputSource source = new InputSource(new StringReader(xmlContents));
			source.setEncoding("UTF-8");
			doc = reader.read(source);
			Element rootElt = doc.getRootElement();
			Iterator<?> iter = rootElt.elementIterator("entry");
			// 遍历head节点
			while (iter.hasNext()) {
				Element elm = (Element) iter.next();
				String stringValue = elm.getStringValue();
				if (StringUtils.isNotBlank(stringValue)) {
					result.put(elm.attribute("key").getStringValue(), stringValue.trim());
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}